"""
向量模型基类 - 策略模式实现
"""

from abc import ABC, abstractmethod
from typing import List

from config.logging_config import get_logger

logger = get_logger(__name__)


class BaseEmb(ABC):
    """向量模型基类，定义统一的接口"""

    def __init__(self, model_name: str, **kwargs):
        """
        初始化向量模型
        
        Args:
            model_name: 模型名称
            **kwargs: 模型特定的配置参数
        """
        self.model_name = model_name
        self.config = kwargs
        self._validate_config()

    @abstractmethod
    def _validate_config(self) -> None:
        """验证配置参数"""
        pass

    @abstractmethod
    def get_emb(self, text: str) -> List[float]:
        """
        获取单个文本的向量表示
        
        Args:
            text: 输入文本
            
        Returns:
            向量列表
        """
        pass

    @abstractmethod
    def encode(self, texts: List[str]) -> List[List[float]]:
        """
        编码多个文本
        
        Args:
            texts: 文本列表
            
        Returns:
            向量列表的列表
        """
        pass

    def encode_batch(self, texts: List[str], batch_size: int = 32) -> List[List[float]]:
        """
        批量编码文本（默认实现）
        
        Args:
            texts: 文本列表
            batch_size: 批次大小
            
        Returns:
            向量列表的列表
        """
        if len(texts) <= batch_size:
            return self.encode(texts)

        results = []
        for i in range(0, len(texts), batch_size):
            batch = texts[i:i + batch_size]
            batch_results = self.encode(batch)
            results.extend(batch_results)

        return results

    def encode_sentences(self, texts: List[str]) -> List[List[float]]:
        """
        编码句子（别名方法）
        
        Args:
            texts: 文本列表
            
        Returns:
            向量列表的列表
        """
        return self.encode(texts)

    def encode_sentence(self, text: str) -> List[float]:
        """
        编码单个句子（别名方法）
        
        Args:
            text: 输入文本
            
        Returns:
            向量列表
        """
        return self.get_emb(text)

    def get_dimension(self) -> int:
        """
        获取向量维度
        
        Returns:
            向量维度
        """
        # 使用一个简单的测试文本获取维度
        test_vector = self.get_emb("test")
        return len(test_vector)

    def similarity(self, text1: str, text2: str) -> float:
        """
        计算两个文本的相似度
        
        Args:
            text1: 第一个文本
            text2: 第二个文本
            
        Returns:
            相似度分数（余弦相似度）
        """
        import numpy as np

        vec1 = np.array(self.get_emb(text1))
        vec2 = np.array(self.get_emb(text2))

        # 计算余弦相似度
        dot_product = np.dot(vec1, vec2)
        norm1 = np.linalg.norm(vec1)
        norm2 = np.linalg.norm(vec2)

        if norm1 == 0 or norm2 == 0:
            return 0.0

        return dot_product / (norm1 * norm2)

    def __str__(self) -> str:
        return f"{self.__class__.__name__}(model_name='{self.model_name}')"

    def __repr__(self) -> str:
        return self.__str__()


class EmbeddingError(Exception):
    """向量模型相关异常"""
    pass


class ConfigurationError(EmbeddingError):
    """配置错误异常"""
    pass


class ModelNotFoundError(EmbeddingError):
    """模型未找到异常"""
    pass
